home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / reve / tty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  21.7 KB  |  807 lines

  1. /*LINTLIBRARY*/
  2.  
  3. /*  @(#)tty.c 1.21 91/11/13
  4.  *
  5.  *  These are the dumb tty dependent graphics routines used by reve.
  6.  *
  7.  *  Copyright (C) 1990, 1991 - Rich Burridge & Yves Gallot.
  8.  *  All rights reserved.
  9.  *
  10.  *  Permission is granted to copy this source, for redistribution
  11.  *  in source form only, provided the news headers in "substantially
  12.  *  unaltered format" are retained, the introductory messages are not
  13.  *  removed, and no monies are exchanged.
  14.  *
  15.  *  Permission is also granted to copy this source, without the
  16.  *  news headers, for the purposes of making an executable copy by
  17.  *  means of compilation, provided that such copy will not be used
  18.  *  for the purposes of competition in any othello tournaments, without
  19.  *  prior permission from the authors.
  20.  *
  21.  *  No responsibility is taken for any errors or inaccuracies inherent
  22.  *  either to the comments or the code of this program, but if reported
  23.  *  (see README file), then an attempt will be made to fix them.
  24.  */
  25.  
  26. #include "reve.h"
  27. #include "color.h"
  28. #include "extern.h"
  29. #include <sys/ioctl.h>
  30. #include <signal.h>
  31.  
  32. #ifdef HASPOLL
  33. #include <poll.h>
  34. #endif /*HASPOLL*/
  35.  
  36. #ifdef SYSV
  37. #include <sgtty.h>
  38. #endif /*SYSV*/
  39.  
  40. #define  DRAW_STRING(col, row, str, v)  draw_string(col, row, str, v), return
  41.  
  42. #define  KEY_INPUT   0       /* Types of input selected on. */
  43. #define  COMP_INPUT  1
  44. #define  SOCK_INPUT  2
  45.  
  46. enum gr_type gtype = GTTY ;  /* Graphics type. */
  47.  
  48. #ifdef NOSELECT
  49. #ifdef HASPOLL
  50. struct pollfd pfd[2] ;
  51. unsigned long npfd ;         /* Number of file descriptors to monitor. */
  52. #endif /*HASPOLL*/
  53. #else NOSELECT
  54. #ifdef NO_43SELECT
  55. int fullmask ;               /* Full mask of file descriptors to check on. */
  56. int readmask ;               /* Readmask used in select call. */
  57. #else
  58. fd_set fullmask ;            /* Full mask of file descriptors to check on. */
  59. fd_set readmask ;            /* Readmask used in select call. */
  60. #endif /*NO_43SELECT*/
  61. #endif /*NOSELECT*/
  62.  
  63. /* NOTE: This is a classic example of reverse engineering. These routines
  64.  *       have been modified (read hacked), to use the same interface as
  65.  *       the pixel graphics ones. Therefore they have to do some strange
  66.  *       checking to make sure everything comes out correctly.
  67.  */
  68.  
  69. char *CE, *CL, *CM, *SE, *SO ;
  70.  
  71. extern char *getenv  P((char *)) ;
  72. extern char *tgetstr P((char *, char **)) ;
  73. extern char *tgoto   P((char *, int, int)) ;
  74.  
  75. struct sgttyb in_new, in_old ;
  76.  
  77. static void do_clr_eol     P(()) ;
  78. static void do_standend    P(()) ;
  79. static void do_standout    P(()) ;
  80. static void draw_string    P((int, int, char *, int)) ;
  81. static void get_event      P(()) ;
  82. static void outc           P((int)) ;
  83. static void outstr         P((char *)) ;
  84. static void tc_move        P((int, int)) ;
  85.  
  86. /* Information for all the panel items. */
  87.  
  88. struct tty_info {     /* Information for all the panel items. */
  89.   int column ;        /* Column number. */
  90.   int row ;           /* Row number. */
  91.   int x ;             /* Pseudo x mouse position. */
  92.   int y ;             /* Pseudo y mouse position. */
  93. } ;
  94.  
  95. struct tty_info ttyvals[MAXITEMS] = {
  96.       {  1,  1,  43,  32, },      /* Load */
  97.       { 11,  1, 117,  32, },      /* Moves? */
  98.       { 22,  1, 191,  32, },      /* New game */
  99.       { -1, -1, 265,  32, },      /* Help   (not displayed). */
  100.       { -1, -1, 339,  32, },      /* Redo   (not displayed). */
  101.       { -1, -1, 413,  32, },      /* Props  (not displayed). */
  102.       { 33,  1,  43,  74, },      /* Save */
  103.       { 44,  1, 117,  74, },      /* Suggest */
  104.       { -1, -1, 191,  74, },      /* Print  (not displayed). */
  105.       { -1, -1, 265,  74, },      /* Stop   (not displayed). */
  106.       { 55,  1, 339,  74, },      /* Undo */
  107.       { -1, -1, 339,  74, },      /* Cancel (not displayed). */
  108.       { -1, -1, 413,  74, },      /* Quit   (not displayed). */
  109.       { 45,  5,  15, 111, },      /* Black: */
  110.       { 45,  7, 237, 111, },      /* White: */
  111.       { -1, -1,  -1,  -1, },      /* Black clock. */
  112.       { -1, -1,  -1,  -1, },      /* White clock. */
  113.       { -1, -1,  -1,  -1, },      /* Panel message. */
  114.       { -1, -1,  -1,  -1, },      /* Notes message. */
  115.       { -1, -1,  -1,  -1, },      /* Score message. */
  116.       { -1, -1,  -1,  -1, },      /* Turn message. */
  117.       { -1, -1,  -1,  -1, },      /* Computer choice.: */
  118.       { -1, -1,  -1,  -1, },      /* Difficulty. */
  119.       { -1, -1,  -1,  -1, },      /* Maximum search depth. */
  120.       { -1, -1,  -1,  -1, },      /* Animate option: */
  121.       { -1, -1,  -1,  -1, },      /* Best computer move option. */
  122.       { -1, -1,  -1,  -1, },      /* Last move option. */
  123.       { -1, -1,  -1,  -1, },      /* Show evaluation option. */
  124.       { -1, -1,  -1,  -1, },      /* Number move option. */
  125.       { -1, -1,  -1,  -1, },      /* Quick game option. */
  126.       { -1, -1,  -1,  -1, },      /* Display clocks. */
  127.       { -1, -1,  -1,  -1, },      /* Help window page cycle.*/
  128. } ;
  129.  
  130. struct other_info {   /* Information needed to place other text values. */
  131.   int column ;        /* Column number. */
  132.   int row ;           /* Row number. */
  133. } ;
  134.  
  135. struct other_info othervals[MAXITEMS] = {
  136.       { -1, -1, },       /* Load     (ignored). */
  137.       { -1, -1, },       /* Moves?   (ignored). */
  138.       { -1, -1, },       /* New game (ignored). */
  139.       { -1, -1, },       /* Help     (ignored). */
  140.       { -1, -1, },       /* Redo     (ignored). */
  141.       { -1, -1, },       /* Props    (ignored). */
  142.       { -1, -1, },       /* Save     (ignored). */
  143.       { -1, -1, },       /* Suggest  (ignored). */
  144.       { -1, -1, },       /* Print    (ignored). */
  145.       { -1, -1, },       /* Stop     (ignored). */
  146.       { -1, -1, },       /* Undo     (ignored). */
  147.       { -1, -1, },       /* Cancel   (ignored). */
  148.       { -1, -1, },       /* Quit     (ignored). */
  149.       { 38,  5, },       /* Black: */
  150.       { 38,  7, },       /* White: */
  151.       { 60,  5, },       /* Black clock. */
  152.       { 60,  7, },       /* White clock. */
  153.       { 38, 13, },       /* Panel message. */
  154.       { 38, 15, },       /* Notes message. */
  155.       { 38, 17, },       /* Score message. */
  156.       { 38, 19, },       /* Turn message. */
  157.       { -1, -1, },       /* Computer choice. */
  158.       { 60,  9, },       /* Difficulty. */
  159.       { -1, -1, },       /* Maximum search depth. */
  160.       { -1, -1, },       /* Animate option: */
  161.       { -1, -1, },       /* Best computer move option. */
  162.       { -1, -1, },       /* Last move option. */
  163.       { 60, 11, },       /* Show evaluation option. */
  164.       { -1, -1, },       /* Number move option. */
  165.       { -1, -1, },       /* Quick game option. */
  166.       { -1, -1, },       /* Display clocks. */
  167.       { -1, -1, },       /* Help window page cycle. */
  168. } ;
  169.  
  170.  
  171. /*ARGSUSED*/
  172. void
  173. batch(state)             /* Graphics batching - null routine. */
  174. enum bltype state ;
  175. {}
  176.  
  177.  
  178. void
  179. beep()
  180. {
  181. }
  182.  
  183.  
  184. void
  185. close_reve()
  186. {
  187. }
  188.  
  189.  
  190. SIGRET
  191. cleanup()
  192. {
  193.   destroy_reve() ;
  194. }
  195.  
  196.  
  197. void
  198. connect_io()     /* Connect to keyboard, computer process and remote human. */
  199. {
  200. #ifdef NOSELECT
  201. #ifdef HASPOLL
  202.   npfd = 0L ;
  203.   pfd[0].fd = pfd[1].fd = pfd[2].fd = -1 ;
  204.   pfd[0].events = pfd[1].events = pfd[2].events = POLLIN ;
  205.                          pfd[0].fd = 0,             npfd++ ;   /* Keyboard. */
  206.   if (pipe_io[1][0] > 0) pfd[1].fd = pipe_io[1][0], npfd++ ;   /* Computer. */
  207.   if (socketfd      > 0) pfd[2].fd = socketfd,      npfd++ ;   /* Human. */
  208. #endif /*HASPOLL*/
  209. #else
  210. #ifdef NO_43SELECT
  211.   fullmask = 0 ;
  212.                          fullmask |= (1 << 0) ;                /* Keyboard. */
  213.   if (pipe_io[1][0] > 0) fullmask |= (1 << pipe_io[1][0]) ;    /* Computer. */
  214.   if (socketfd      > 0) fullmask |= (1 << socketfd) ;         /* Human. */
  215. #else
  216.   FD_ZERO(&fullmask) ;
  217.                          FD_SET(0,             &fullmask) ;    /* Keyboard. */
  218.   if (pipe_io[1][0] > 0) FD_SET(pipe_io[1][0], &fullmask) ;    /* Computer. */
  219.   if (socketfd      > 0) FD_SET(socketfd,      &fullmask) ;    /* Human. */
  220. #endif /*NO_43SELECT*/
  221. #endif /*NOSELECT*/
  222. }
  223.  
  224.  
  225. /*ARGSUSED*/
  226. void
  227. color_area(wtype, x, y, width, height, color)
  228. enum win_type wtype ;
  229. int x, y, width, height, color ;
  230. {
  231.   char nextline[MAXLINE] ;
  232.  
  233. /*  There are two cases we care about here:
  234.  *
  235.  *  (1) If the width is TOTAL_WIDTH and the height is TOTAL_HEIGHT, then
  236.  *      we clear the whole of the screen. We also draw the board at this
  237.  *      time. With the pixel based graphics versions, this is normally
  238.  *      done by low-level graphics routines, but to fully emulate that is
  239.  *      just too hard.
  240.  *
  241.  *  (2) When we are "undo"ing a piece. A check is made to if the width and
  242.  *      the height of the area we are coloring is PSIZE. If so, then we
  243.  *      display a space at the appropriately adjusted row/column.
  244.  */
  245.  
  246.   if (width == BOARD_DIM && height == BOARD_DIM)
  247.     {
  248.       tputs(CL, 1, outc) ;
  249.       tc_move(4, 3) ;
  250.       outstr("a   b   c   d   e   f   g   h") ;
  251.       for (y = 4; y < 21; y++)
  252.         {
  253.           tc_move(1, y) ;
  254.           if (y % 2)
  255.             SPRINTF(nextline, "%c|   |   |   |   |   |   |   |   |%c",
  256.                               '1' + (y - 4) / 2, '1' + (y - 4) / 2) ;
  257.           else       SPRINTF(nextline, " +---+---+---+---+---+---+---+---+") ;
  258.           outstr(nextline) ;
  259.         }
  260.       tc_move(4, 21) ;
  261.       outstr("a   b   c   d   e   f   g   h") ;
  262.     }
  263.   else if (width == PSIZE && height == PSIZE)
  264.     {
  265.       tc_move(4 + 4 * (((x - BBORDER - PIECE_MARGIN) / CELL_SIZE) & 7),
  266.               5 + 2 * ((y  - BBORDER - PIECE_MARGIN) / CELL_SIZE)) ;
  267.       outc(' ') ;
  268.     }
  269. }
  270.  
  271.  
  272. void
  273. destroy_reve()                /* Terminate Reve. */
  274. {
  275.   KILL(pid, SIGKILL) ;
  276.   tputs(CL, 1, outc) ;
  277.   SIGNAL(SIGINT, SIG_IGN) ;
  278.   IOCTL(0, TIOCSETP, &in_old) ;
  279.   exit(0) ;
  280. }
  281.  
  282.  
  283. static void
  284. do_clr_eol()                  /* Clear to the end of the line. */
  285. {
  286.   tputs(CE, 1, outc) ;
  287. }
  288.  
  289.  
  290. static void
  291. do_standend()                 /* Finish inverted area. */
  292. {
  293.   tputs(SE, 1, outc) ;
  294. }
  295.  
  296.  
  297. static void
  298. do_standout()                 /* Start inverted area. */
  299. {
  300.   tputs(SO, 1, outc) ;
  301. }
  302.  
  303.  
  304. /*ARGSUSED*/
  305. void
  306. draw_image(wtype, x, y, width, height, image)    /* Null routine. */
  307. enum win_type wtype ;
  308. int x, y, width, height ;
  309. enum image_type image ;
  310. {}
  311.  
  312.  
  313. /*ARGSUSED*/
  314. void
  315. draw_line(wtype, x1, y1, x2, y2, op, color)
  316. enum win_type wtype ;
  317. int x1, y1, x2, y2, color ;
  318. enum optype op ;
  319. {
  320.   char ch ;
  321.  
  322. /*  There is just one case we care about here; the "suggest" cross. To
  323.  *  determine if this is such a case, we check if the two x values differ
  324.  *  by 10, and the two y values differ by 10. If so, then a plus sign is
  325.  *  output at the appropriate row/column, if the color is black, otherwise
  326.  *  a space is output.
  327.  */
  328.  
  329.   if (abs(x1 - x2) == 10 && abs(y1 - y2) == 10)
  330.     {
  331.       ch = '+' ;
  332.       tc_move(4 + 4 * (((x1 - BBORDER - PIECE_MARGIN) / CELL_SIZE) & 7),
  333.               5 + 2 * ((y1  - BBORDER - PIECE_MARGIN) / CELL_SIZE)) ;
  334.       if (color != C_BLACK) ch = ' ' ;
  335.       outc(ch) ;
  336.     }
  337. }
  338.  
  339.  
  340. /*ARGSUSED*/
  341. void
  342. draw_stencil(wtype, x, y, width, height, op, color, stencil, image)
  343. enum win_type wtype ;
  344. int x, y, width, height, color ;
  345. enum optype op ;
  346. enum image_type stencil, image ;
  347. {
  348.   int ch ;
  349.  
  350.        if (image == P_BLACK) ch = 'X' ;
  351.   else if (image == P_WHITE) ch = 'O' ;
  352.   else return ;
  353.        if (op == RCLR) ch = ' ' ;
  354.   else if (op == RINV) return ;
  355.  
  356.   tc_move(8 + 4 * (((x - BBORDER - PIECE_MARGIN) / CELL_SIZE) & 7),
  357.           7 + 2 * ((y  - BBORDER - PIECE_MARGIN) / CELL_SIZE)) ;
  358.   outc(ch) ;
  359. }
  360.  
  361.  
  362. static void
  363. draw_string(x, y, str, flag)    /* Display str at x,y. */
  364. int x,y, flag ;
  365. char *str ;
  366. {
  367.  
  368. /*  If flag is set, then we clear to the end of line, otherwise we
  369.  *  display the text str in reverse video.
  370.  */
  371.  
  372.   if (flag)
  373.     {
  374.       tc_move(x, y) ;
  375.       do_clr_eol() ;
  376.     }
  377.   else do_standout() ;
  378.  
  379.   tc_move(x, y) ;
  380.   outstr(str) ;
  381.   if (!flag) do_standend() ;
  382. }
  383.  
  384.  
  385. /*  Text can be one of three things:
  386.  *
  387.  *  (1) Text for "panel" items.
  388.  *  (2) Text for "cyclic" items.
  389.  *  (3) Other text.
  390.  *
  391.  *  First we check to see if this is one of the panel message strings.
  392.  *
  393.  *  Next we check if this is a panel button or cycle types.
  394.  *
  395.  *  For all other text, we check where it is being displayed against
  396.  *  a list of possible values. This is then remapped to the correct
  397.  *  row/column number, and displayed.
  398.  */
  399.  
  400. /*ARGSUSED*/
  401. void
  402. draw_text(wtype, x, y, ftype, color, str)
  403. enum win_type wtype ;
  404. enum font_type ftype ;
  405. int x, y, color ;
  406. char *str ;
  407. {
  408.   enum panel_type pt ;
  409.   int black, white ;
  410.   int i ;
  411.  
  412. /* Check if we are inputting a load/save filename. */
  413.  
  414.   if (x == 89  && y == 74)
  415.     {
  416.       draw_string(38, 3, str, TRUE) ;  /* File: */
  417.       return ;
  418.     }
  419.   else if (x == 136 && y == 74)
  420.     {
  421.       draw_string(45, 3, str, TRUE) ;  /* filename */
  422.       return ;
  423.     }
  424.  
  425. /* Check for the six panel message types. */
  426.  
  427.   else if (x == 15 && y == 111 && wtype == W_PANEL)   /* Black: message. */
  428.     {
  429.       draw_string(othervals[(int) BLACK_PLAYS].column,
  430.                   othervals[(int) BLACK_PLAYS].row, str, FALSE) ;
  431.       return ;
  432.     }
  433.   else if (x == 237 && y == 111 && wtype == W_PANEL)  /* White: message. */
  434.     {
  435.       draw_string(othervals[(int) WHITE_PLAYS].column,
  436.                   othervals[(int) WHITE_PLAYS].row, str, FALSE) ;
  437.       return ;
  438.     }
  439.   else if (x == 15 && y == 195 && wtype == W_PANEL)   /* Panel message. */
  440.     {
  441.       if (EQUAL(str, "Use left"))
  442.         STRCPY(str, "Select a letter/number pair for a move") ;
  443.       draw_string(othervals[(int) PANEL_MES].column,
  444.                   othervals[(int) PANEL_MES].row, str, TRUE) ;
  445.       return ;
  446.     }
  447.   else if (x == 15 && y == 237)       /* Evaluation message. */
  448.     {
  449.       draw_string(othervals[(int) EVAL_MES].column,
  450.                   othervals[(int) EVAL_MES].row, str, TRUE) ;
  451.       return ;
  452.     }
  453.   else if (x == 15 && y == 279)        /* Score message. */
  454.     {
  455.       if (sscanf(str, "Stones: Black: %d White: %d", &black, &white) == 2)
  456.         SPRINTF(str, "Black (X): %d, White (O): %d", black, white) ;
  457.       draw_string(othervals[(int) SCORE_MES].column,
  458.                   othervals[(int) SCORE_MES].row, str, TRUE) ;
  459.       return ;
  460.     }
  461.   else if (x == 237 && y == 279)       /* Turn message. */
  462.     {
  463.       draw_string(othervals[(int) TURN_MES].column,
  464.                   othervals[(int) TURN_MES].row, str, TRUE) ;
  465.       return ;
  466.     }
  467.  
  468. /* Check for the two "Time Left:" and two clock values. */
  469.  
  470.   else if (x == 15 && y == 153 && wtype == W_PANEL)   /* Black Time Left. */
  471.     {
  472.       draw_string(othervals[(int) BLACK_CLOCK].column,
  473.                   othervals[(int) BLACK_CLOCK].row, str, TRUE) ;
  474.       return ;
  475.     }
  476.   else if (x == 237 && y == 153 && wtype == W_PANEL)  /* White Time Left. */
  477.     {
  478.       draw_string(othervals[(int) WHITE_CLOCK].column,
  479.                   othervals[(int) WHITE_CLOCK].row, str, TRUE) ;
  480.       return ;
  481.     }
  482.  
  483.   else if (x == 105 && y == 153 && wtype == W_PANEL)  /* Black clock value. */
  484.     {
  485.       if (!DO_CLOCK) STRCPY(str, "     ") ;
  486.       draw_string(othervals[(int) BLACK_CLOCK].column+11,
  487.                   othervals[(int) BLACK_CLOCK].row, str, TRUE) ;
  488.       return ;
  489.     } 
  490.   else if (x == 327 && y == 153 && wtype == W_PANEL)  /* White clock value. */
  491.     {
  492.       if (!DO_CLOCK) STRCPY(str, "     ") ;
  493.       draw_string(othervals[(int) WHITE_CLOCK].column+11,
  494.                   othervals[(int) WHITE_CLOCK].row, str, TRUE) ;
  495.       return ;
  496.     }
  497.  
  498. /* Check for the two player strings. */
  499.  
  500.   else if (x == 89 && y == 111 && wtype == W_PANEL)  /* Black plays: value. */
  501.     {
  502.       draw_string(ttyvals[(int) BLACK_PLAYS].column,
  503.                   ttyvals[(int) BLACK_PLAYS].row, str, TRUE) ;
  504.       return ;
  505.     }
  506.   else if (x == 311 && y == 111 && wtype == W_PANEL) /* White plays: value. */
  507.     {
  508.       draw_string(ttyvals[(int) WHITE_PLAYS].column,
  509.                   ttyvals[(int) WHITE_PLAYS].row, str, TRUE) ;
  510.       return ;
  511.     }
  512.  
  513. /* Check for panel and cyclic items. */
  514.  
  515.   for (i = 0; i < MAXITEMS-13; i++)
  516.     if (EQUAL(str, items[i].text))
  517.       if (ttyvals[i].column != -1)
  518.         {
  519.                if (EQUAL(str, "load"))     STRCPY(str, "Load") ;
  520.           else if (EQUAL(str, "moves?"))   STRCPY(str, "Moves?") ;
  521.           else if (EQUAL(str, "save"))     STRCPY(str, "Save") ;
  522.           else if (EQUAL(str, "show all")) STRCPY(str, "show All") ;
  523.           draw_string(ttyvals[i].column, ttyvals[i].row, str, FALSE) ;
  524.           return ;
  525.         }
  526.       else return ;
  527.  
  528. /* Other text. */
  529.  
  530.   switch (y)
  531.     {
  532.       case 111  : if (x == 163) pt = BLACK_PLAYS ;      /* Black plays. */
  533.                   else          pt = WHITE_PLAYS ;      /* White plays. */
  534.                   break ;
  535.       case 153  : if (x == 163) pt = DIFF_CHOICE ;      /* Difficulty. */
  536.                   else          pt = OPT_EVAL ;         /* Notes. */
  537.                   break ;
  538.       default   : return ;   /* We're not interested in this piece of text. */
  539.     }
  540.   draw_string(othervals[(int) pt].column, othervals[(int) pt].row,
  541.               str, TRUE) ;
  542. }
  543.  
  544.  
  545. static void
  546. get_event()            /* Only events possible are keyboard ones. */
  547. {
  548.   struct timeval tval ;    /* Set to go off once a second. */
  549.   char c ;
  550.   int fd, reply ;
  551.  
  552.   fd    = -1 ;
  553.   nextc = IGNORE_EVENT ;
  554.   tc_move(0, 0) ;          /* Get that bloody cursor out of the way. */
  555.   tval.tv_usec = 0 ;
  556.   tval.tv_sec  = 1 ;
  557.  
  558. #ifdef NOSELECT
  559. #ifdef HASPOLL
  560.   POLL(pfd, npfd, -1) ;
  561.        if (pfd[0].revents == POLLIN) fd = KEY_INPUT ;
  562.   else if (pfd[1].revents == POLLIN) fd = COMP_INPUT ;
  563.   else if (pfd[2].revents == POLLIN) fd = SOCK_INPUT ;
  564. #else
  565.   FPRINTF(stderr, "This situation in not being properly handled yet.\n") ;
  566. #endif /*HASPOLL*/
  567. #else
  568.   readmask = fullmask ;
  569. #ifdef NO_43SELECT
  570.   SELECT(32, &readmask, 0, 0, &tval) ;
  571.        if (readmask && (1 << 0))             fd = KEY_INPUT ;
  572.   else if (readmask && (1 << pipe_io[1][0])) fd = COMP_INPUT ;
  573.   else if (readmask && (1 << socketfd))      fd = SOCK_INPUT ;
  574. #else
  575.   SELECT(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &tval) ;
  576.        if (FD_ISSET(0,             &readmask)) fd = KEY_INPUT ;
  577.   else if (FD_ISSET(pipe_io[1][0], &readmask)) fd = COMP_INPUT ;
  578.   else if (FD_ISSET(socketfd,      &readmask)) fd = SOCK_INPUT ;
  579. #endif /*NO_43SELECT*/
  580. #endif /*NOSELECT*/
  581.  
  582.   switch (fd)
  583.     {
  584.       case KEY_INPUT  : READ(0, &c, 1) ;
  585.                         cur_ch = c & 0177 ;
  586.                         if (cur_ch == 12) nextc = BOARD_REPAINT ;
  587.                         else              nextc = KEYBOARD ;
  588.                         break ;
  589.       case SOCK_INPUT : read_from_sock(socketfd) ;    /* Remote human. */
  590.                         break ;
  591.       case COMP_INPUT : read_from_reve(pipe_io[1][0]) ;   /* Computer. */
  592.     }
  593.   if (cmode != GAME_OVER) update_clock(next_player, FALSE) ;
  594. }
  595.  
  596.  
  597. char *
  598. get_resource(rtype)      /* Null routine (currently only X11 and XView). */
  599. enum res_type rtype ;
  600. {
  601.   return((char *) NULL) ;
  602. }
  603.  
  604.  
  605. /*ARGSUSED*/
  606. int
  607. get_strwidth(ftype, str)    /* Get width in pixels of string value. */
  608. enum font_type ftype ;
  609. char *str ;
  610. {
  611.   return(8 * strlen(str)) ;
  612. }
  613.  
  614.  
  615. void
  616. init_fonts()             /* Open normal and bold fonts. */
  617. {
  618.   int i ;
  619.  
  620.   for (i = 0; i < MAXFONTS; i++) font_heights[i] = 12 ;
  621. }
  622.  
  623.  
  624. /*ARGSUSED*/
  625. void
  626. init_graphics(argc, argv)
  627. int *argc ;
  628. char *argv[] ;
  629. {
  630. }
  631.  
  632.  
  633. int
  634. init_ws_type()
  635. {
  636.   char bp[1024], termtype[MAXLINE] ;
  637.   static char buf[100] ;
  638.   char *area = buf ;
  639.  
  640.   if (getenv("TERM") != NULL) STRCPY(termtype, getenv("TERM")) ;
  641.   if (tgetent(bp, termtype) != 1) return 1 ;
  642.   if ((CL = tgetstr("cl", &area)) == (char *) 0) return 1 ;
  643.   if ((CM = tgetstr("cm", &area)) == (char *) 0) return 1 ;
  644.   if ((CE = tgetstr("ce", &area)) == (char *) 0) return 1 ;
  645.   if ((SO = tgetstr("so", &area)) == (char *) 0) return 1 ;
  646.   if ((SE = tgetstr("se", &area)) == (char *) 0) return 1 ;
  647.  
  648.   gtype         = GTTY ;   /* Graphics type. */
  649.   move_delta    = 5 ;
  650.   props_showing = TRUE ;   /* Force choice item sizes to be calculated. */
  651.   return(0) ;
  652. }
  653.  
  654.  
  655. static void
  656. load_colors()     /* No colors in the termcap implementation. */
  657. {
  658.   iscolor = 0 ;
  659. }
  660.  
  661.  
  662. void
  663. load_resources()     /* Dummy routine; used with X11 and XView versions. */
  664. {
  665. }
  666.  
  667.  
  668. /*ARGSUSED*/
  669. void
  670. lock_screen(state)     /* Graphics locking - null routine. */
  671. enum bltype state ;
  672. {}
  673.  
  674.  
  675. void
  676. make_canvas()               /* Null routine, see the make_frame routine. */
  677. {}
  678.  
  679.  
  680. /*ARGSUSED*/
  681. void
  682. make_frame(argc, argv)      /* Create reve window/icon. */
  683. int argc ;
  684. char *argv[] ;
  685. {
  686.   SIGNAL(SIGINT, cleanup) ;
  687.   IOCTL(0, TIOCGETP, &in_old) ;        /* Setup standard input. */
  688.   in_new = in_old ;
  689.   in_new.sg_flags |= RAW ;
  690.   in_new.sg_flags &= ~(ECHO | CRMOD) ;
  691.   IOCTL(0, TIOCSETP, &in_new) ;
  692.   setbuf(stdout, (char *) NULL) ;
  693.   pid = fork_child() ;
  694. }
  695.  
  696.  
  697. /*ARGSUSED*/
  698. void
  699. make_help_window(argc, argv)
  700. int argc ;
  701. char *argv[] ;
  702. {
  703. }
  704.  
  705.  
  706. void
  707. make_icon()             /* Null routine - no icon in termcap version. */
  708. {}
  709.  
  710.  
  711. void
  712. make_pieces(width, height)
  713. int width, height ;
  714. {
  715.   bborder = BBORDER ;
  716.  
  717.   cell_width   = (width  - (2 * bborder)) / BOARD_SIZE ;
  718.   cell_height  = (height - (2 * bborder)) / BOARD_SIZE ;
  719.  
  720.   pieceXmargin = cell_width  / 8 ;
  721.   pieceYmargin = cell_height / 8 ;
  722.   pieceXrad    = (cell_width  - (2 * pieceXmargin)) / 2 ;
  723.   pieceYrad    = (cell_height - (2 * pieceYmargin)) / 2 ;
  724. }
  725.  
  726.  
  727. static void
  728. outc(c)                 /* Output the next character to the screen. */
  729. register int c ;
  730. {
  731.   PUTC(c, stdout) ;
  732. }
  733.  
  734.  
  735. static void
  736. outstr(str)
  737. char *str ;
  738. {
  739.   register int i ;
  740.  
  741.   for (i = 0; i < strlen(str); i++) PUTC(str[i], stdout) ;
  742. }
  743.  
  744.  
  745. void
  746. open_reve()
  747. {
  748. }
  749.  
  750.  
  751. void
  752. process_event()           /* Process the next user input. */
  753. {
  754.   if (nextc == BOARD_REPAINT)
  755.     {
  756.       paint_board() ;
  757.       paint_panel() ;
  758.       nextc = IGNORE_EVENT ;
  759.     }
  760. }
  761.  
  762.  
  763. void
  764. raise_reve()
  765. {
  766. }
  767.  
  768.  
  769. /*ARGSUSED*/
  770. void
  771. set_cursor(cursor)        /* No cursors in termcap version. */
  772. enum curtype cursor ;
  773. {}
  774.  
  775.  
  776. /*ARGSUSED*/
  777. void
  778. set_frame(wtype, showing)
  779. enum win_type wtype ;
  780. int showing ;
  781. {
  782.   if (wtype == W_PROPS) paint_prop_sheet() ;
  783. }
  784.  
  785.  
  786. /*ARGSUSED*/
  787. void
  788. start_tool(dtype)            /* Display screen and start event dispatcher. */
  789. enum disp_type dtype ;
  790. {
  791.   paint_all() ;
  792.  
  793.   for (;;)
  794.     {
  795.       get_event() ;          /* Get next canvas event. */
  796.       handle_event() ;       /* And do the appropriate action. */
  797.     }
  798. }
  799.  
  800.  
  801. static void
  802. tc_move(x, y)                 /* Move to character position (x, y). */
  803. int x, y ;
  804. {
  805.   tputs(tgoto(CM, x, y), 1, outc) ;
  806. }
  807.